package com.centriole.service.workflow.controller.ex;

import com.centriole.common.utils.PaasResult;
import com.centriole.common.component.EurekaClientUtils;
import com.centriole.common.feignApi.PaasUserFeignClient;
import com.centriole.service.workflow.dao.ProcessMapper;
import com.centriole.service.workflow.entity.Function;
import com.centriole.service.workflow.entity.ProInstance;
import com.centriole.service.workflow.entity.Process;
import com.centriole.service.workflow.entity.WorkPage;
import com.centriole.service.workflow.service.FunctionService;
import com.centriole.service.workflow.service.ProcessService;
import com.centriole.service.workflow.service.WorkPageService;
import com.centriole.service.workflow.service.vo.CompleteTaskRequest;
import com.netflix.discovery.converters.Auto;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 *  功   能：对外暴露的工作流API
 *  创建人：陈默晗
 *  时   间：2018年4月25日上午10:40:18
 */
@RestController
@RequestMapping(value = "/ex",produces = "application/json;charset=utf-8")
public class ExController {

    @Autowired
    ProcessService processService;

    @Autowired
    ExService exService;

    @Autowired
    PaasUserFeignClient paasUserFeignClient;

    @Autowired
    WorkPageService workPageService;

    @Autowired
    ProcessMapper processMapper;

    @Autowired
    FunctionService functionService;

    @Value("${spring.application.name}")
    String serverId;

    @Value("${workflow.url}")
    String workflowUrl;

    @RequestMapping("/hello")
    public PaasResult hello(String startUserId , String processId , String appId , String userId){
        return PaasResult.success("hello~~! startUserId = " + startUserId + " , processId = " + processId + " , appId = " +appId +" , userId = " + userId );
    }

    @RequestMapping("/pro")
    public PaasResult hello(){
        return PaasResult.success(paasUserFeignClient.listAllApps());
    }

    /*
     * 用户创建一个流程定义
     * @return  Data中主要是 页面的编辑地址    比如：flow/process/processEditBpmn?id=13245678456132
     */
    @RequestMapping("/process/save")
    public PaasResult createProcess(Process model, HttpServletRequest request){
    
        try {
            String userId = getCreatorId(request);
            model.setCreatorId(userId);
            model.setModifierId(userId);
            String httpHostUrl = EurekaClientUtils.getServiceUrlByRamdon(serverId.toUpperCase() , workflowUrl);
            String pid = processService.editProcess(model);
            return PaasResult.success("ok",httpHostUrl+"/flow/process/processEditBpmn?id="+pid);
        } catch (Exception e) {
        	e.printStackTrace();
            return PaasResult.error("创建流程错误");
        }
    }

    /**
     * 指定userId查询待办任务
     * @param userId            指定用户id
     * @param appName       应用名，只在查询与该应用下的待办任务
     * @return
     */
    @RequestMapping(value = "/myHandling")
    public PaasResult myHandling(String userId , String appName){
        String httpHostUrl = EurekaClientUtils.getServiceUrlByRamdon(serverId.toUpperCase() ,workflowUrl );
        PaasResult checkResult = checkUserIdAndAppName(userId, appName);
        return checkResult==null?PaasResult.success("ok",httpHostUrl + "/flow/task/toTaskList?userId="+userId +"&appName="+appName):checkResult;
    }

    /**
     * 获取指定用户的已办理的流程（该用户已操作过的流程）
     * @param userId            指定用户id
     * @param appName       应用名，只在查询与该应用下的待办任务
     * @return
     */
    @RequestMapping(value = "/myFinished")
    public PaasResult myFinished(String userId , String appName){
        String httpHostUrl = EurekaClientUtils.getServiceUrlByRamdon(serverId.toUpperCase() , workflowUrl);
        PaasResult checkResult = checkUserIdAndAppName(userId, appName);
        return checkResult==null?PaasResult.success("ok",httpHostUrl + "/flow/task/toTaskMyHistory?userId="+userId +"&appName="+appName):checkResult;
    }

    /**
     * 获取指定用户发起的在进行中的流程（由该用户发起的流程）
     * @param userId            指定用户id
     * @param appName       应用名，只在查询与该应用下的待办任务
     * @return
     */
    @RequestMapping(value = "/myOngoing")
    public PaasResult myOngoing(String userId , String appName){
        String httpHostUrl = EurekaClientUtils.getServiceUrlByRamdon(serverId.toUpperCase() , workflowUrl);
        PaasResult checkResult = checkUserIdAndAppName(userId, appName);
        return checkResult==null?PaasResult.success("ok",httpHostUrl + "/flow/task/toTaskMyProcess?userId="+userId +"&appName="+appName):checkResult;
    }

    /**
     * 获取指定用户的操作过的流程（该用户参与过的所有流程）
     * @param userId            指定用户id
     * @param appName       应用名，只在查询与该应用下的待办任务
     * @return
     */
    @RequestMapping(value = "/myDealed")
    public PaasResult myDealed(String userId , String appName){
        String httpHostUrl = EurekaClientUtils.getServiceUrlByRamdon(serverId.toUpperCase() , workflowUrl);
        PaasResult checkResult = checkUserIdAndAppName(userId, appName);
        return checkResult==null?PaasResult.success("ok",httpHostUrl + "/flow/task/toTaskDealList?userId="+userId +"&appName="+appName):checkResult;
    }

    /**
     * 通过"流程定义key"来部署流程
     * @param processKey
     * @return
     */
    @RequestMapping(value = "/deploy")
    public PaasResult deploy(String processKey){
        Process process = processMapper.selectByProcessKey(processKey);
        try {
            processService.deploy(process.getId());
            return PaasResult.success("部署成功");
        }catch (Exception e){
            e.printStackTrace();
            return PaasResult.error("部署发生异常");
        }

    }

    /**
     *  用户发起一个流程
     * @param proInstance   流程的id
     * @return
     */
    @RequestMapping("/start")
    public PaasResult start(ProInstance proInstance , HttpServletRequest request){
        if (proInstance.getProcessId().equals("")) {
            return PaasResult.fail("流程id不能为空!");
        }
        if(StringUtils.isBlank( proInstance.getStartUserId() )){
            return PaasResult.fail("流程发起用户id不能为空!");
        }
        try {
            String instanceId = processService.start(proInstance, request);
            return PaasResult.success(proInstance.getStartUserId()+" 发起[processId="+proInstance.getProcessId()+"]流程成功", instanceId);
        } catch (Exception e) {
            return PaasResult.fail(e.getMessage());
        }
    }

    /**
     *  用户暂停一个流程
     * @param proInstance   流程的id
     * @return
     */
    @PostMapping("/pause")
    public PaasResult pasue(ProInstance proInstance){
        try {
            processService.suspendInstance(proInstance.getInstanceId());
            return PaasResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return PaasResult.error("流程暂停失败，请联系管理员");
        }
    }

    /**
     *  用户继续一个被暂停的流程
     * @param proInstance   流程的id
     * @return
     */
    @PostMapping("/resume")
    public PaasResult resume(ProInstance proInstance){
        try {
            processService.activateInstance(proInstance.getInstanceId());
            return PaasResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            return PaasResult.error("继续流程失败，请联系管理员");
        }
    }

    /**
     *  用户完成当前任务节点，完成后，继续下一个任务节点
     * @param startUserId 提交人
     * @param task   一个已开始流程实例的当前任务节点( 抽象成了一个CompleteTaskRequest，用来描述当前任务节点的相关信息 )
     * @return
     */
    @PostMapping("/compete")
    public PaasResult compete(String startUserId, String approverId ,CompleteTaskRequest task){
        if (task.getTaskId() == null)
            return PaasResult.fail("流程实例的任务id为空");
        try {
            boolean result = processService.useCompleteTask(task , startUserId , approverId);
            if (!result) {
                return PaasResult.fail("任务已被其他成员完成");
            }
        } catch (Exception ce) {
            ce.printStackTrace();
            return PaasResult.error("在办理任务时发生了未知错误，请联系开发人员");
        }
        return PaasResult.success();
    }


    /**
     * 添加单据
     * @param page
     * @return
     */
    @RequestMapping("/addPage")
    public PaasResult addVeiwPage(WorkPage page){
        try {
            workPageService.insertOrEdit(page);
            return PaasResult.success("添加页面成功");
        } catch (Exception e) {
            e.printStackTrace();
            return PaasResult.error("添加页面时出现了错误");
        }
    }

    /**
     * 添加操作方法
     * @param function
     * @return
     */
    @RequestMapping("/addFunction")
    public PaasResult addFunction(Function function){
        try {
            functionService.insertOrEdit(function);
            return PaasResult.success("添加方法成功");
        } catch (Exception e) {
            e.printStackTrace();
            return PaasResult.error("添加方法时出现了错误");
        }

    }

    @RequestMapping("/callback")
    public PaasResult fakeCallBackUrl(String instanceId , String  startUserId , String reviewResult ,String approverId){
        Map<String , String > map = new HashMap<>();
        map.put("instanceId",instanceId);
        map.put("startUserId",startUserId);
        map.put("reviewResult",reviewResult);
        map.put("approverId",approverId);
        System.err.println("【调用回调接口】");
        map.entrySet().forEach(System.err::println);
        return PaasResult.success("我是回调接口!",map);
    }

    @RequestMapping("/view")
    public PaasResult fakeVUrl(String id ){
        return PaasResult.success("查看页面，当前查看的modelId = " + id);
    }


    private String getCreatorId(HttpServletRequest request) {
        String userId = (String)	request.getParameter("userId");
        return userId == null ? "default" : userId;
    }


    private PaasResult checkUserIdAndAppName(String userId , String appName){
        if(StringUtils.isBlank(userId)){
            return PaasResult.error("userId不能为空");
        }
        if(StringUtils.isBlank(appName)){
            return PaasResult.error("appName不能为空");
        }
        return null;
    }

}
